﻿// <author>Diogo Silva 11238</author>
// <author>Raúl Gonçalo Palma 11392</author>
// <date>26/01/2015</date>

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Windows.Forms.DataVisualization.Charting;

namespace CSharpProject
{
    public partial class ShowGraphs : Form
    {

        DbHandler db;

        /// <summary>
        ///  Construtor da classe ShowGraphs.
        /// </summary>
        public ShowGraphs()
        {
            InitializeComponent();
            this.db = new DbHandler();
        }

        private void ShowGraphs_Load(object sender, EventArgs e)
        {
            this.listaGraficos.SelectedIndex = 0;
        }

        /// <summary>
        ///  Função responsável pela apresentação dos gráficos.
        ///  param name="field" - Campo da tabela
        ///  param name="points" - Lista com os anos e valores correspondentes
        /// </summary>
        private void plotGraph(int field, Tuple<List<int>, List<double>> points)
        {
            String title = "";
            String yAxisLabel = "";
            switch (field)
            {
                case DbHandler.FIELD_IPC:
                    {
                        title = "Variação do IPC Global com o decorrer dos anos";
                        yAxisLabel = "IPC Global";
                        break;
                    }
                case DbHandler.FIELD_VARANUAL:
                    {
                        title = "Variação da Variação Anual com o decorrer dos anos";
                        yAxisLabel = "Variação Anual";
                        break;
                    }
                case DbHandler.FIELD_REMUNMINMENSAL:
                    {
                        title = "Variação da Remuneração Míninma Mensal com o decorrer dos anos";
                        yAxisLabel = "Remuneração Míninma Mensal";
                        break;
                    }
                case DbHandler.FIELD_REMUNMAXMENSAL:
                    {
                        title = "Variação da Remuneração Máxima Mensal com o decorrer dos anos";
                        yAxisLabel = "Remuneração Máxima Mensal";
                        break;
                    }
                case DbHandler.FIELD_PIB:
                    {
                        title = "Variação do Produto Interno Bruto com o decorrer dos anos";
                        yAxisLabel = "Produto Interno Bruto";
                        break;
                    }
                case DbHandler.FIELD_RENDNACIONALBRUTO:
                    {
                        title = "Variação do Rendimento Nacional Bruto com o decorrer dos anos";
                        yAxisLabel = "Rendimento Nacional Bruto";
                        break;
                    }
                case DbHandler.FIELD_RENDDISPLBRUTOANUAL:
                    {
                        title = "Variação do Rendimento Disponível Bruto Anual com o decorrer dos anos";
                        yAxisLabel = "Rendimento Disponível Bruto Anual";
                        break;
                    }
                case DbHandler.FIELD_REMUNPERCAPITAANUAL:
                    {
                        title = "Variação da Remuneração Per Capita Anual com o decorrer dos anos";
                        yAxisLabel = "Remuneração Per Capita Anual";
                        break;
                    }

                case DbHandler.FIELD_EVOREMUNMIN:
                    {
                        title = "Variação da Evolução da Remuneração mínima mensal com o decorrer dos anos";
                        yAxisLabel = "Evolução da Remuneração mínima mensal";
                        break;
                    }

                case DbHandler.FIELD_EVOREMUNMAX:
                    {
                        title = "Variação da Evolução da Remuneração máxima mensal com o decorrer dos anos";
                        yAxisLabel = "Evolução da Remuneração máxima mensal";
                        break;
                    }
            }
            this.graph.Series.Clear();
            Series serie = new Series
            {
                Name = title,
                Color = System.Drawing.Color.Red,
                IsVisibleInLegend = true,
                IsXValueIndexed = true,
                ChartType = SeriesChartType.Line
            };

            Series serieMedia = new Series
            {
                Name = "Média",
                Color = System.Drawing.Color.LimeGreen,
                IsVisibleInLegend = true,
                IsXValueIndexed = true,
                ChartType = SeriesChartType.Line
            };

            Series serieMediana = new Series
            {
                Name = "Mediana",
                Color = System.Drawing.Color.Blue,
                IsVisibleInLegend = true,
                IsXValueIndexed = true,
                ChartType = SeriesChartType.Line
            };

            Series serieStdDesviation = new Series
            {
                Name = "Desvio Padrão",
                Color = System.Drawing.Color.Orange,
                IsVisibleInLegend = true,
                IsXValueIndexed = true,
                ChartType = SeriesChartType.Line
            };

            this.graph.Series.Add(serie);
            this.graph.Series.Add(serieMedia);
            this.graph.Series.Add(serieMediana);
            this.graph.Series.Add(serieStdDesviation);

            List<int> years = points.Item1;
            List<double> values = points.Item2;

            double averageValue = values.Average();
            double medianValue = calcMedian(values);
            double stdValue  = calcStandardDeviation(values);

            for (int i = 0; i < years.Count; i++)
            {
                serie.Points.AddXY(years[i], values[i]);
                serieMedia.Points.AddXY(years[i], averageValue);
                serieMediana.Points.AddXY(years[i], medianValue);
                serieStdDesviation.Points.AddXY(years[i], stdValue);
            }

            this.graph.ChartAreas["ChartArea1"].AxisX.Title = "Anos";

            this.graph.ChartAreas["ChartArea1"].AxisY.Title = yAxisLabel;

            this.graph.ChartAreas["ChartArea1"].RecalculateAxesScale();

            // Set automatic zooming
            this.graph.ChartAreas["ChartArea1"].AxisX.ScaleView.Zoomable = true;
            this.graph.ChartAreas["ChartArea1"].AxisY.ScaleView.Zoomable = true;

            // Set automatic scrolling 
            this.graph.ChartAreas["ChartArea1"].CursorX.AutoScroll = true;
            this.graph.ChartAreas["ChartArea1"].CursorY.AutoScroll = true;

            // Allow user selection for Zoom
            this.graph.ChartAreas["ChartArea1"].CursorX.IsUserSelectionEnabled = true;
            this.graph.ChartAreas["ChartArea1"].CursorY.IsUserSelectionEnabled = true;

            this.graph.Invalidate();

            this.avarege.Text = Math.Round(averageValue, 2).ToString();

            this.median.Text = Math.Round(medianValue, 2).ToString();

            this.variance.Text = Math.Round(calcVariance(values), 2).ToString();

            this.stdDeviation.Text = Math.Round(stdValue, 2).ToString();
        }

        /// <summary>
        ///  Função responsável pelo cálculo da Mediana.
        ///  param name="values" - lista com os valores correspondentes aos anos indicados
        /// </summary>
        private static double calcMedian(List<double> values)
        {
            double[] temp = values.ToArray();
            Array.Sort(temp);

            double median = 0.0;

            if (temp.Length % 2 == 0)
            {
                double a = temp[(temp.Length / 2) - 1];
                double b = temp[temp.Length / 2];
                median = (a + b) / 2;
            }
            else
            {
                median = temp[temp.Length / 2];
            }

            return median;
        }

        /// <summary>
        ///  Função responsável pelo cálculo da Variância.
        ///  param name="values" - lista com os valores correspondentes aos anos indicados
        /// </summary>
        private static double calcVariance(List<double> values)
        {
            double sum = 0.0;
            double variance = 0.0;

            for (int i = 0; i < values.Count; i++)
            {
                sum += (values[i] - values.Average()) * (values[i] - values.Average());
                variance = sum / (values.Count - 1);
            }

            return variance;
        }

        /// <summary>
        ///  Função responsável pelo cálculo do Desvio Padrão.
        ///  param name="values" - lista com os valores correspondentes aos anos indicados
        /// </summary>
        private static double calcStandardDeviation(List<double> values)
        {
            double result = 0.0;
            result = Math.Sqrt(calcVariance(values));
            return result;
        }

        private void mostrarGrafico_Click(object sender, EventArgs e)
        {
            int initYear;
            int finalYear;
            try
            {
                 initYear = Int32.Parse(this.inputInitYear.Text);
            }
            catch
            {
                System.Windows.Forms.MessageBox.Show("Introduza um inteiro no ano inicial!");
                return;
            }

            try
            {
                 finalYear = Int32.Parse(this.inputFinalYear.Text);
            }
            catch
            {
                System.Windows.Forms.MessageBox.Show("Introduza um inteiro no ano final!");
                return;
            }
            
            int field = this.listaGraficos.SelectedIndex;

            this.plotGraph(field, this.db.query(initYear, finalYear, field));
        }

        private void carregarXLSToolStripMenuItem_Click(object sender, EventArgs e)
        {
            OpenFileDialog openFileDialog1 = new OpenFileDialog();

            // Set filter options and filter index.
            openFileDialog1.Filter = "Excel Files (.xls)|*.xls";


            // Process input if the user clicked OK.
            if (openFileDialog1.ShowDialog() == DialogResult.OK)
            {
                ReadXlsFile read = new ReadXlsFile();
                this.db.clearTable();
                this.db.InsertData(read.ReadXls(openFileDialog1.FileName));
                System.Windows.Forms.MessageBox.Show("O ficheiro foi carregado com sucesso!");
            }

        }

        private void abrirToolStripMenuItem_Click(object sender, EventArgs e)
        {
            System.Windows.Forms.Application.Exit();
        }
    }
}
